import {
	createApp
} from 'vue';
import router from './router/index.js';
import store from './store/index.js';


/**
 * @param {Object} el
 * @param {String} hover
 * @param {String} leave
 */
function hoverLeaveAnimation(el, hover, leave) {
	function hoverHandler() {
		//添加 hover class
		el.classList.add(hover)

	}

	function leveHndler() {
		el.classList.remove(hover)
		endsTimeAnimation(el, leave)
	}
	return {
		"hover": hoverHandler,
		"leave": leveHndler
	}
}


/**
 * @param {String} claEl
 * @param {String} type
 * @param {Function} handler
 */
function unitElsAddEvent(claEl, type, handler) {
	let unitEls = document.getElementsByClassName(claEl)
	// console.log(unitEls);
	for (var i = 0; i < unitEls.length; i++) {
		// console.log(unitEls[i]);
		unitEls[i].addEventListener(type, handler)
	}
}


function windowShade() {
	let body = document.body
	let shadeEl = document.createElement("div")
	shadeEl.classList.add("window_shade")
	shadeEl.id = "window__shade"
	SetStaticCssTxt("shadow",
		`.window_shade {
	width: 100vw;
	height: 100vh;
	display: none;
	// backdrop-filter: blur(.5px);
	// background-color: rgba(57,55,51,.6);

	// z-index: 98;
	z-index: -1;

	position: fixed;
	top: 0;
	left: 0;
}`
	)
	body.appendChild(shadeEl)
	return shadeEl
}


//挂载组件
function mountComponent(id, url) {
	return import(`@/components/${url}`).then(e => {
		// console.log(e.default);
		let newApp = createApp(e.default);
		newApp.use(store).use(router);
		newApp.mount(id);
		return newApp
	})
}

/**
 * 展示 元素
 * --目標元素 延迟添加 和 class animation 和 延遲删除 
 * @param {Object} el	--目標元素
 * @param {Object} animate	-- 動畫class
 * @param {Object} delay	-- 延遲添加
 * @param {Object} lateDrop	-- 延遲刪除
 * 
 * @return {Number} --延迟添加 和 animation 的時間 和 延遲删除 所用的時間
 */
function endsTimeAnimation(el, animate, delay, lateDrop) {
	if (!(el instanceof HTMLElement) || animate == undefined) {
		return 0
	}
	//返回結果
	let delayResult = 0

	delay = delay == undefined ? 0 : delay

	lateDrop = lateDrop == undefined ? 0 : lateDrop

	setTimeout(() => {
		// console.log(el);
		el.classList.add(animate);

		let comedEl = window.getComputedStyle(el);
		// console.log(comedEl);

		//目标 class 延迟时间
		let totalDelay = eval(parseFloat(comedEl.animationDuration.slice(0, -1)) + parseFloat(comedEl.animationDelay.slice(
			0,
			-1)));
		// console.log(totalDelay);

		setTimeout(() => {
			el.classList.remove(animate);
		}, Number(delay) + Number(totalDelay * 1000) + Number(lateDrop));
	}, delay)

	//賦值空元素 模擬計算 一次
	if (window.calcdomAnimateDelayEl == undefined) {
		let vac = document.createElement("div")
		document.appendChild(vac)
		window.calcdomAnimateDelayEl = vac
	}
	window.calcdomAnimateDelayEl.classList.add(animate)
	let a = window.getComputedStyle(window.calcdomAnimateDelayEl)
	let classDelay = eval(parseFloat(a.animationDuration.slice(0, -1)) + parseFloat(a.animationDelay.slice(
		0,
		-1)));
	//移除 模拟计算的 class
	window.calcdomAnimateDelayEl.classList.remove(animate)

	delayResult = Number(delay) + Number(classDelay * 1000) + Number(lateDrop)

	return delayResult
}


/**
 * @param {String} className
 * @param {String} style_3
 */
function tipsMount(className, style_3) {
	//需要 calssname classname_animation tray___classname_animation 三个class 样式
	let app = document.querySelector('#app');
	let tipsEl = document.createElement('div');
	tipsEl.className = `${className} tray___${className}_animation`;
	tipsEl.id = className.replace('_', '__');
	SetStaticCssTxt(`${className}_TipStyle_Anima`, style_3);
	app.appendChild(tipsEl);
}


/**
 * 建立 唯一 臨時的 style 標簽 到 head 
 * @param {String} id
 */
function SetStaticCssTxtFunc(id) {
	window.StaticCss = window.StaticCss ? function() {
		let a = window.StaticCss
		a["id"].indexOf(id) == -1 ? function() {
			a["id"].push(id)
			a[id] = {
				classArr: []
			}
		}() : undefined
		return a

	}() : function() {
		let a = {}
		a["id"] = [id]
		a[id] = {
			classArr: []
		}
		return a
	}()
	let totalStaticCss = window.StaticCss

	function avanda(cla, code) {
		if (cla == undefined && code == undefined) {
			//返回 縂的 已經定義的 元素
			return claArr
		}
		// console.log(claArr);
		if (cla == undefined) {
			console.log("sorry we need a id to manage the variable \n plase enter a arguments[0] value")

			return null
		}


		var hasClaCss = false
		// console.log("沒進來 ");
		let claArr = totalStaticCss[id]
		// console.log(claArr);

		claArr["classArr"].indexOf(cla) == -1 ? function() {
			// console.log("添加")
			claArr["classArr"].push(cla)
			claArr[cla] = code
		}() : function() {
			hasClaCss = true
			// console.log("添加過了")

			//cover style code
			let targetStyle = document.getElementById(cla)
			try {
				//for Chrome Firefox Opera Safari
				targetStyle.appendChild(document.createTextNode(code))
			} catch (ex) {
				//for IE
				targetStyle.styleSheet.cssText = code
			}
		}()


		if (hasClaCss == true) {
			// console.log("you have settled \"" + cla + "\" id CssStyle Now!  In head tag");
			return true
		}
		if (code != undefined) {
			var style = document.createElement('style')
			style.type = 'text/css'
			style.rel = 'stylesheet'
			try {
				//for Chrome Firefox Opera Safari
				style.appendChild(document.createTextNode(code))
			} catch (ex) {
				//for IE
				style.styleSheet.cssText = code
			}
			style.setAttribute("class", `static_${cla}`)
			style.setAttribute("id", `${cla}`)

			var head = document.getElementsByTagName('head')[0]
			head.appendChild(style)
		} else if (code == "remove") {
			if (claArr["classArr"].indexOf(cla) != -1) {
				claArr["classArr"].splice(claArr["classArr"].indexOf(cla), 1)
				// console.log(claArr);
				var claEle = document.getElementById(`${cla}`)
				claEle.remove()
				return `${cla} has been removed`
			}
			return `${cla} is undefined`
		} else if (code == undefined) {
			if (claArr["classArr"].indexOf(cla) != -1) {
				//返回 指定的 class
				return claArr["classArr"][cla]
			}
			return `${cla} is undefined`
		}

	}

	return avanda
}


/**
 * @param {Object} a
 * @param {String} type
 */
//tostring 类型检测 a 数据源 type 数据类型 （不分大小写）
function toStringTypeCheck(a, type) {
	if (type == undefined) {
		return toString.call(a).slice(8, -1).toLowerCase()
	} else if (type.toLowerCase() == "any") {
		return true
	}
	// console.log(toString.call(a).slice(8, -1))
	return toString.call(a).slice(8, -1).toLowerCase() == type.toLowerCase()
}

function trayElClass(el, index, use) {
	let prefix = "tray___"
	use = (use === undefined || use === false) ? false : true

	//use true 是 启用
	if (use) {
		// console.log(toStringTypeCheck(index, "number"));
		if (toStringTypeCheck(index, "number")) {
			if (el.classList[index].indexOf(prefix) > -1) {
				// console.log(el.classList[index].splice(0, 7));
				let targetClass = el.classList[index]
				el.classList.remove(targetClass)
				el.classList.add(targetClass.slice(7, -1))

				return true
			} else {
				console.log(`sorry this index:${index} we did not disabled`);
				return false
			}
		} else if (toStringTypeCheck(index, "string")) {
			for (let i = 0; i < el.classList.length; i++) {
				// console.log(el.classList[i].indexOf(prefix), el.classList[i].indexOf(index));
				if (el.classList[i].indexOf(prefix) == 0 && el.classList[i].indexOf(index) == 7) {
					// console.log(el.classList[i].splice(0, 7));
					let targetClass = el.classList[i]
					// console.log(targetClass);
					el.classList.remove(targetClass)
					// console.log(targetClass.slice(7));
					el.classList.add(targetClass.slice(7))
					return true
				} else if (el.classList[i].indexOf(prefix) == -1 && el.classList[i].indexOf(index) == 0) {
					return true
				}
			}
			console.log(`sorry this className:${prefix+index} is not in this Element classList`);
			return false
		} else {
			console.log("sorry we got wrong type of index(at arguments[1]) \n we need a \"Number\" or \"String\" type");
			return false
		}
	}
	//use false 是 禁用
	else {
		// console.log(toStringTypeCheck(index, "number"));
		if (toStringTypeCheck(index, "number")) {
			if (el.classList[index] != undefined) {
				// el.classList[index] = prefix+el.classList[index]
				let targetClass = el.classList[index]
				el.classList.remove(targetClass)
				el.classList.add(prefix + targetClass)
				return true
			} else {
				console.log(`sorry this index:${index} is overflow the stack \n the classList length is ${el.classList.length}`);
				return false
			}
		} else if (toStringTypeCheck(index, "string")) {
			for (let i = 0; i < el.classList.length; i++) {
				// console.log(el.classList[i].indexOf(index));
				if (el.classList[i].indexOf(prefix) == -1 && el.classList[i].indexOf(index) == 0) {
					// el.classList[i] = prefix + el.classList[i]
					let targetClass = el.classList[i]
					el.classList.remove(targetClass)
					el.classList.add(prefix + targetClass)
					return true
				} else if (el.classList[i].indexOf(prefix) == 0 && el.classList[i].indexOf(index) == 7) {
					return true
				}
			}
			console.log(`sorry this className:${index} is not in this Element ${el.classList} classList`);
			return false
		} else {
			console.log("sorry we got wrong type of index(at arguments[1]) \n we need a \"Number\" or \"String\" type");
			return false
		}
	}
}

function debounce(fn, delay) {
	let time = undefined
	return () => {
		if (time == undefined) {
			fn()
			time = delay
			setTimeout(() => {
				time = undefined
			}, delay)
		} else {
			return
		}
	}
}

/**
 * @param {String} className
 * @param {String} querySelectorAll
 */
function childNodes(className, querySelectorAll) {
	let result
	let bodyEl = document.getElementsByClassName(className)[0];
	// console.log(bodyEl);
	if (querySelectorAll == 'all' || querySelectorAll == undefined) {
		result = bodyEl.children;
		// console.log(result);
	} else if (toStringTypeCheck(querySelectorAll, "string")) {
		result = document.querySelectorAll(querySelectorAll)
		// console.log(result);
	}
	return result
}


/**
 * @param {styleSheet} styleSheet
 * @param {String} name
 * @param {String} str
 */
function changeKeyframesString(styleSheet, name, str) {
	let NewstyleText = ''
	let result = -1
	for (let i = 0; i < styleSheet.cssRules.length; i++) {

		if (toStringTypeCheck(styleSheet.cssRules[i], 'CSSKeyframesRule') && styleSheet.cssRules[i].name == name) {
			styleSheet.deleteRule(i);
			styleSheet.insertRule(str, i);
			result = i
		}
		NewstyleText = `${NewstyleText}\n ${styleSheet.cssRules[i].cssText}`
		// console.log(NewstyleText);
	}
	styleSheet.ownerNode.innerHTML = NewstyleText
	return result
}

function spliteMatrix(matrStr, type) {
	if (!toStringTypeCheck(matrStr, 'string')) {
		console.log('sorry the arguments[0] is not String type');
		return false;
	}
	//matrix(1, 0, 0, 1, 0, -41.6)
	//matrix\((?<scalX>-?\d+(?:\.\d+)?),\s(?<skew>-?\d+(?:\.\d+)?),\s(?<rotate>-?\d+(?:\.\d+)?),\s(?<scalY>-?\d+(?:\.\d+)?),\s(?<translateX>-?\d+(?:\.\d+)?),\s(?<translateY>-?\d+(?:\.\d+)?)\)
	let resultArr = [];
	let regMatrixStr =
		/matrix\((?<scalX>-?\d+(?:\.\d+)?),\s(?<skew>-?\d+(?:\.\d+)?),\s(?<rotate>-?\d+(?:\.\d+)?),\s(?<scalY>-?\d+(?:\.\d+)?),\s(?<translateX>-?\d+(?:\.\d+)?),\s(?<translateY>-?\d+(?:\.\d+)?)\)/;
	let matchResult = matrStr.match(regMatrixStr);
	if (matchResult.groups) {
		for (let key in matchResult.groups) {
			resultArr[key] = matchResult.groups[key];
		}
		// console.log(resultArr);
		if (type != undefined) {
			if (!toStringTypeCheck(type, 'string')) {
				console.log('sorry the arguments[1] is not String type');
				return false;
			}
			return resultArr[type];
		} else {
			return resultArr;
		}
	}
}

/**
 * @param {Object} el
 */
function removableElement(el, {
	x0,
	y0,
	x1,
	y1
}) {
	let elOffsetX
	let elOffsetY

	let comedEl = window.getComputedStyle(el)
	// console.log(comedEl);
	//添加 el 上的 mouseDown 事件
	el.addEventListener("mousedown", mouseDownHandle)

	function mouseDownHandle(event) {
		elOffsetX = event.offsetX
		elOffsetY = event.offsetY


		window.addEventListener('mousemove', settleMouseMove);
		window.addEventListener('mouseup', mouseUpHandle);
	}

	//mousemove 鼠标 离开
	function mouseUpHandle() {
		window.removeEventListener('mousemove', settleMouseMove);
		window.removeEventListener('mouseup', mouseUpHandle);
	}

	//修改 el 元素的 位置 和 透明值
	function setElePosition(x, y, opacity) {
		el.setAttribute('style', `left: ${x}px;top: ${y}px;opacity:${opacity == undefined ? 1 : opacity};`);
	}

	//mousemove 鼠标 移动 事件
	function settleMouseMove(event) {

		let setX = event.pageX - elOffsetX;
		let setY = event.pageY - elOffsetY;

		if (setX < x0) {
			setX = x0
		}
		// console.log(rangeX-parseFloat(comedEl.width) );
		if (setX > x1 - parseFloat(comedEl.width)) {
			setX = x1 - parseFloat(comedEl.width)
		}


		if (setY < y0) {
			setY = y0
		}

		// console.log(rangeY - parseFloat(comedEl.height));
		if (setY > y1 - parseFloat(comedEl.height)) {
			setY = y1 - parseFloat(comedEl.height)
		}


		//设置 偏移
		setElePosition(setX, setY);
	}

}


/**
 * 獲取 元素的 絕對 視窗定位
 * @param {Object} el 元素對象
 * @param {Object} str ["top"||"left"]
 * @return {Number}
 */
function getbodyOffsetPosition(el, str) {
	let keys = 'offset' + str[0].toUpperCase() + str.substring(1);
	let translateDire = str == 'top' ? 'translateY' : 'translateX';
	// console.log(keys);
	let num = 0;
	let elclone = el;
	for (; elclone['offsetParent'] != null;) {
		console.log(window.getComputedStyle(elclone));
		let matrixstr = window.getComputedStyle(elclone)['transform'];
		if (matrixstr != 'none') {
			let trans = spliteMatrix(matrixstr, translateDire);
			// console.log(trans);
			num += Number(trans);
		}
		// console.log(elclone, elclone['offsetParent']);
		num += Number(elclone[keys]);
		// console.log(num);
		elclone = elclone['offsetParent'];
	}
	return num;
}



let SetStaticCssTxt = SetStaticCssTxtFunc()
export {
	getbodyOffsetPosition,
	removableElement,
	spliteMatrix,
	SetStaticCssTxtFunc,
	SetStaticCssTxt,
	childNodes,
	debounce,
	endsTimeAnimation,
	hoverLeaveAnimation,
	mountComponent,
	tipsMount,
	toStringTypeCheck,
	trayElClass,
	unitElsAddEvent,
	windowShade,
	changeKeyframesString

}
// let arr = [
// 	'childNodes',
// 	'toStringTypeCheck',
// 	'SetStaticCssTxt',
// 	'trayElClass',
// 	'debounce',
// 	'tipsMount',
// 	'endsTimeAnimation',
// 	'mountComponent',
// 	'windowShade',
// 	'unitElsAddEvent',
// 	'hoverLeaveAnimation'
// ];
// console.log(arr.sort());
